﻿using System;

namespace PoolKit
{
    /// <summary>
    /// Functional shortcut for creating a <see cref="RepairStrategy{TResource}"/>
    /// </summary>
    /// <typeparam name="TResource">Type of resource the strategy can handle</typeparam>
    public class RepairFunction<TResource> : RepairStrategy<TResource>
    {
        private readonly Func<TResource, TResource> _repairFunction;
        private readonly ThreadingContract _threadingContract;

        /// <summary>
        /// Creates a repair strategy from the provided function
        /// </summary>
        /// <param name="repairFunction">Function that defines the strategy</param>
        /// <param name="threadingContract">Specifies the threading contract exposed by the strategy (whether it is safe to call into the strategy simultaneously from several threads).</param>
        /// <exception cref="ArgumentNullException"></exception>
        public RepairFunction(Func<TResource, TResource> repairFunction, ThreadingContract threadingContract)
        {
            if (repairFunction == null) throw new ArgumentNullException("repairFunction");

            _repairFunction = repairFunction;
            _threadingContract = threadingContract;
        }

        /// <summary>
        /// True, if it is safe to call into the strategy simultaneously from several threads; False - otherwise.
        /// </summary>
        public override ThreadingContract ThreadingContract
        {
            get
            {
                return _threadingContract;
            }
        }

        /// <summary>
        /// Repairs a broken resource or creates a replacement for it
        /// </summary>
        /// <param name="resource">Resource to repair</param>
        /// <returns>Repaired resource or a replacement for it</returns>
        public override TResource Repair(TResource resource)
        {
            return _repairFunction.Invoke(resource);
        }
    }
}